package com.power.sifa.base.service.impl;

import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import com.power.sifa.base.service.ChatRobotService;
import com.power.sifa.util.service.impl.ChatListener;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.WebSocket;
import org.springframework.stereotype.Service;

/**
 * 讯飞星火AI机器人
 * @author 81814
 *
 */
@Slf4j
@Service
public class ChatRobotImpl implements ChatRobotService {
    public static final String hostUrl = "https://spark-api.xf-yun.com/v3.5/chat";
    public static final String appid = "74229b27";
    public static final String apiSecret = "ZmFlY2JlNWI2NGYzZmY1OWJhMjRkZjRm";
    public static final String apiKey = "fd48bde084e5d74b83135356d6492baa";

    /**
     * 每次启用socket时拼装鉴权地址
     * @return
     * @throws Exception
     */
    public static String getAuthUrl() throws Exception {
        URL url = new URL(hostUrl);
        // 时间
        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        Calendar now=Calendar.getInstance();
        Date nowdate=now.getTime();
        String date = format.format(nowdate);
        // 拼接
        String preStr = "host: " + url.getHost() + "\n" +
                "date: " + date + "\n" +
                "GET " + url.getPath() + " HTTP/1.1";
//        log.info("getAuthUrl preStr:{}", preStr);
        // SHA256加密
        Mac mac = Mac.getInstance("hmacsha256");
        SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "hmacsha256");
        mac.init(spec);

        byte[] hexDigits = mac.doFinal(preStr.getBytes(StandardCharsets.UTF_8));
        // Base64加密
        String sha = Base64.getEncoder().encodeToString(hexDigits);
//      log.info("getAuthUrl sha:{}", sha);
        // 拼接
        String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);
        // 拼接地址
        String httpUrl="https://" + url.getHost() + url.getPath()+"?authorization="+Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8))
        		+ "&date=" + URLEncoder.encode(date, StandardCharsets.UTF_8.toString()).replaceAll("\\+", "%20")
        		+ "&host=" + url.getHost();
//      log.info("getAuthUrl httpUrl:{}", httpUrl);
        return httpUrl;
    }

    /**
     * 提问并等待回答
     * 内部是异步操作，用while进行等待同步化
     * 会创建socket连接，完成问询回答，再关闭连接
     * @param newQuestion
     * @return
     * @throws Exception
     */
    public static String getChat(String newQuestion) throws Exception {
        String authUrl = ChatRobotImpl.getAuthUrl();
        String url = authUrl.toString().replace("http://", "ws://").replace("https://", "wss://");
        Request request = new Request.Builder().url(url).build();
        OkHttpClient client = new OkHttpClient.Builder().build();
        ChatListener listener= new ChatListener(ChatRobotImpl.appid, newQuestion);
        WebSocket webSocket = client.newWebSocket(request, listener);

        while(webSocket.queueSize()==0 && listener.isRunning()) {
        	Thread.sleep(100);
        }
        String answer=listener.getAnswer();
        listener=null;
        return answer;
    }

    @Override
    public String aiSearch(String question) throws Exception {
//        String newQuestion="关于拆迁补偿的法律条款";
        String authUrl = ChatRobotImpl.getAuthUrl();
        String url = authUrl.replace("http://", "ws://").replace("https://", "wss://");
        Request request = new Request.Builder().url(url).build();
        OkHttpClient client = new OkHttpClient.Builder().build();
        ChatListener listener= new ChatListener(ChatRobotImpl.appid, question);
        WebSocket webSocket = client.newWebSocket(request, listener);
        // 等待会话结果
        while(webSocket.queueSize()==0 && listener.isRunning()) {
        	Thread.sleep(500);
        }
        return listener.getAnswer();
    }
}
